﻿using System;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using PolePosition.v3.Common;

namespace PolePosition.v3.Desktop.Grids
{
    public partial class GridBase : UserControl
    {
        public GridBase()
        {
            InitializeComponent();
        }
        
        public GridBase(Enumerations.DataTypes gridDataType)
        {
            InitializeComponent();
            saveFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            CurrentSearchType = Enumerations.GridSearchByTpes.None;
            GridDataType = gridDataType;
            PageSize = 100;
            PageNumber = 1;

            buttonItemFirst.Enabled = false;
            buttonItemPrevious.Enabled = false;
            comboBoxItemPages.Enabled = false;
            buttonItemNext.Enabled = false; 
            buttonItemLast.Enabled = false;
        }

        public string DataDescription
        {
            get { return panelExTitle.Text; }
            set { panelExTitle.Text = value; }
        }

        [DefaultValue(1)]
        public int PageNumber { get; set; }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int TotalPages { get; set; }

        [DefaultValue(100)]
        public int PageSize { get; set; }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int TotalItems { get; set; }

        [DefaultValue(true)]
        public bool TitleVisible 
        {
            get { return panelExTitle.Visible; }
            set { panelExTitle.Visible = value; }
        }
        
        [DefaultValue(true)]
        public bool PagingVisible
        {
            get { return itemContainerPaging.Visible; }
            set { itemContainerPaging.Visible = value; }
        }
        
        [DefaultValue(true)]
        public bool ExportToExcelVisible
        {
            get { return buttonItemExcel.Visible; }
            set { buttonItemExcel.Visible = value; }

        }
        
        [DefaultValue(true)]
        public bool MapVisible
        {
            get { return buttonItemMap.Visible; }
            set { buttonItemMap.Visible = value; }
        }

        [DefaultValue(false)]
        public bool ViewOnMapItemVisible
        {
            get { return buttonItemViewOnMap.Visible; }
            set { buttonItemViewOnMap.Visible = value; }
        }

        [DefaultValue(true)]
        public bool SearchVisible
        {
            get { return buttonItemSearch.Visible; }
            set { buttonItemSearch.Visible = value; }
        }

        [DefaultValue(null), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        private string m_Kml;
        public string Kml 
        {
            get { return m_Kml; }
            set { m_Kml = value; } 
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Enumerations.DataTypes GridDataType { get; private set; }

        private int m_DataKeyId = -1;
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int DataKeyId
        {
            get { return m_DataKeyId; }
            set
            {
                if (m_DataKeyId != value)
                    Kml = null;

                m_DataKeyId = value;
            }
        }

        [DefaultValue(false)]
        private bool m_EditContextAllowed;
        public bool EditContextAllowed
        {
            get { return m_EditContextAllowed; }
            set { m_EditContextAllowed = value; }
        }

        [DefaultValue(null), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public decimal? SelectedRowLongitude { get; set; }

        [DefaultValue(null), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public decimal? SelectedRowLatitude { get; set; }

        private bool m_DirectionLocationsLoaded;
        private void LoadDirectionLocations()
        {
            if (Program.LookupTableData == null)
                return;

            var _Offices = from office in Program.LookupTableData.CentralOffices
                           where office.UtilityFk == Program.UserSelections.UtilityId
                                    && !string.IsNullOrEmpty(office.Address)
                           select office;


            if (_Offices == null || _Offices.Count() == 0)
            {
                buttonItemDirections.Visible = false;
            }
            else
            {
                buttonItemDirections.Visible = true;
                buttonItemDirections.SubItems.Clear();

                DevComponents.DotNetBar.ButtonItem _LocationButton;
                foreach (EntityLibrary.CentralOfficeEntity _Office in _Offices)
                {
                    _LocationButton = new DevComponents.DotNetBar.ButtonItem();
                    _LocationButton.ImagePaddingHorizontal = 8;
                    _LocationButton.Text = _Office.Name;
                    _LocationButton.Tag = _Office.Latitude.Value.ToString().Replace(",", ".") + "," + _Office.Longitude.Value.ToString().Replace(",", ".");
                    _LocationButton.Click += buttonItemDirections_Click;

                    buttonItemDirections.SubItems.Add(_LocationButton);
                }
            }

            m_DirectionLocationsLoaded = true;
        }

        #region Progess Indicator
        
        protected void StartProgressIndicator()
        {
            buttonItemFirst.Enabled = false;
            buttonItemPrevious.Enabled = false;
            comboBoxItemPages.Enabled = false;
            buttonItemNext.Enabled = false;
            buttonItemLast.Enabled = false;
            buttonItemSearch.Enabled = false;
            buttonItemExcel.Enabled = false;
            buttonItemRefresh.Enabled = false;
            buttonItemMap.Enabled = false;
            buttonItemGo.Enabled = false;
            buttonItemClearText.Enabled = false;
            textBoxItemSearch.Enabled = false;

            progressBarItem1.ProgressType = DevComponents.DotNetBar.eProgressItemType.Marquee;
        }

        protected void StopProgressIndicator()
        {
            progressBarItem1.ProgressType = DevComponents.DotNetBar.eProgressItemType.Standard;
            progressBarItem1.Value = 0;

            if (TotalItems != 0)
            {
                buttonItemSearch.Enabled = true;
                buttonItemExcel.Enabled = true;
                buttonItemRefresh.Enabled = true;
                buttonItemMap.Enabled = true;
                buttonItemGo.Enabled = true;
                buttonItemClearText.Enabled = true;
                textBoxItemSearch.Enabled = true;
            }
        }

        #endregion

        #region Asynch GetKml

        protected void StartAsynchGetKml()
        {
            //if (!string.IsNullOrEmpty(Kml))
            //{
            //    if (Program.FormMain.MapControl.KMLType == this.GridDataType)
            //        Program.FormMain.ShowMapTab();
            //    else
            //        ShowKmlInMap();
            //    return;
            //}

            StartProgressIndicator();

            if (!backgroundWorkerGetKml.IsBusy)
                backgroundWorkerGetKml.RunWorkerAsync();
        }

        public virtual void DoAsynchGetKml(DoWorkEventArgs e)
        {
            //do nothing - all work should be implemented in parent
        }

        protected void CancelAsynchGetKml()
        {
            if (backgroundWorkerGetKml.IsBusy)
                backgroundWorkerGetKml.CancelAsync();
        }

        public virtual void AsychGetKmlComplete(object sender, RunWorkerCompletedEventArgs e)
        {
            //should be implemented in parent with call to base
            StopProgressIndicator();
            SetupPageControls();
        }

        protected bool AsynchGetKmlBusy
        {
            get
            {
                return backgroundWorkerGetKml.IsBusy;
            }
        }

        protected bool AsynchGetKmlCancellationPending
        {
            get
            {
                return backgroundWorkerGetKml.CancellationPending;
            }
        }

        private void backgroundWorkerGetKml_DoWork(object sender, DoWorkEventArgs e)
        {
            DoAsynchGetKml(e);

            if ((sender as BackgroundWorker).CancellationPending)
                e.Cancel = true;
        }

        private void backgroundWorkerGetKml_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
                return;

            AsychGetKmlComplete(sender, e);
        }

        #endregion

        #region Asynch Load

        protected void StartAsynchLoad()
        {
            StartProgressIndicator();

            if (!backgroundWorkerLoad.IsBusy)
                backgroundWorkerLoad.RunWorkerAsync();
        }

        public virtual void DoAsynchLoad(DoWorkEventArgs e)
        {
            //do nothing - all work should be implemented in parent
        }

        protected void CancelAsynchLoad()
        {
            if (backgroundWorkerLoad.IsBusy)
                backgroundWorkerLoad.CancelAsync();
        }

        public virtual void AsychLoadComplete(object sender, RunWorkerCompletedEventArgs e)
        {
            //should be implemented in parent with call to base
            StopProgressIndicator();
            SetupPageControls();

            if (!m_DirectionLocationsLoaded)
                LoadDirectionLocations();
        }

        protected bool AsynchLoadBusy
        {
            get { return backgroundWorkerLoad.IsBusy; }
        }

        protected bool AsynchLoadCancellationPending
        {
            get { return backgroundWorkerLoad.CancellationPending; }
        }

        private void backgroundWorkerLoad_DoWork(object sender, DoWorkEventArgs e)
        {
            DoAsynchLoad(e);

            if ((sender as BackgroundWorker).CancellationPending)
                e.Cancel = true;
        }

        private void backgroundWorkerLoad_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
                return;

            AsychLoadComplete(sender, e);
        }

        #endregion


        #region Asynch Excel Export

        private void backgroundWorkerExcelExport_DoWork(object sender, DoWorkEventArgs e)
        {
            DataSet _Data = null;
            DataTable _Table = null;
            switch (GridDataType)
            {
                case Enumerations.DataTypes.None:
                    break;
                case Enumerations.DataTypes.AssetsXmission:
                    _Data = ServiceProxy.UtilityService.GetXmissionAssetExcelData(DataKeyId, CurrentSearchType, CurrentSearchText);
                    break;
                case Enumerations.DataTypes.AssetsDistribution:
                    _Data = ServiceProxy.UtilityService.GetDistributionAssetExcelData(DataKeyId, CurrentSearchType, CurrentSearchText);
                    break;
                case Enumerations.DataTypes.AssetsMeters:
                    _Data = ServiceProxy.UtilityService.GetMeterAssetExcelData(DataKeyId, CurrentSearchType, CurrentSearchText);
                    break;
                case Enumerations.DataTypes.AssetsTransformers:
                    _Data = ServiceProxy.UtilityService.GetTransformerAssetExcelData(DataKeyId, CurrentSearchType, CurrentSearchText);
                    break;
                case Enumerations.DataTypes.ProjectsXmissionInspection:
                    _Data = ServiceProxy.UtilityService.GetXmissionInspectionProjectPoleExcelData(DataKeyId, CurrentSearchType, CurrentSearchText);
                    break;
                case Enumerations.DataTypes.ProjectsXmissionGpsVisit:
                    _Data = ServiceProxy.UtilityService.GetXmissionGpsProjectPoleExcelData(DataKeyId, CurrentSearchType, CurrentSearchText);
                    break;
                case Enumerations.DataTypes.ProjectsDistributionInspection:
                    _Data = ServiceProxy.UtilityService.GetDistributionInspectionProjectExcelData(DataKeyId, CurrentSearchType, CurrentSearchText);
                    break;
                case Enumerations.DataTypes.ProjectsDistributionGpsVisit:
                    break;
                case Enumerations.DataTypes.WorkQueueXmission:
                case Enumerations.DataTypes.WorkQueueDistribution:
                case Enumerations.DataTypes.WorkQueueMeter:
                    break;
                case Enumerations.DataTypes.Custom:
                    break;
                default:
                    break;
            }

            if ((sender as BackgroundWorker).CancellationPending)
                e.Cancel = true;

            if (_Data != null && _Data.Tables.Count > 0)
                _Table = _Data.Tables[0];

            e.Result = _Table;
        }

        private void backgroundWorkerExcelExport_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            StopProgressIndicator();
            SetupPageControls();

            if (e.Cancelled)
                return;

            if (e.Error != null || e.Result == null)
            {
                DevComponents.DotNetBar.MessageBoxEx.Show("Error retrieving data for excel.",
                    "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            ShowExcelExportResults(e.Result as DataTable);
        }

        #endregion

        #region Asynch Save

        protected void StartAsynchSave()
        {

        }

        public virtual void DoAsynchSave(DoWorkEventArgs e)
        {
            //do nothing - all work should be implemented in parent
        }

        public virtual void AsychSaveComplete(object sender, RunWorkerCompletedEventArgs e)
        {
            //should be implemented in parent with call to base
        }

        #endregion

        #region Change Page

        private bool m_SuspendIndexChanged;
        public void SetupPageControls()
        {
            if (TotalItems == 0)
            {
                buttonItemFirst.Enabled = false;
                buttonItemPrevious.Enabled = false;
                comboBoxItemPages.Items.Clear();
                comboBoxItemPages.Enabled = false;
                buttonItemNext.Enabled = false;
                buttonItemLast.Enabled = false;
                return;
            }



            //determine the total number of pages
            TotalPages = (TotalItems / PageSize) + 1;


            if (PageNumber == 1)
            {
                buttonItemFirst.Enabled = false;
                buttonItemPrevious.Enabled = false;
            }
            else
            {
                buttonItemFirst.Enabled = true;
                buttonItemPrevious.Enabled = true;
            }

            if (PageNumber == TotalPages)
            {
                buttonItemNext.Enabled = false;
                buttonItemLast.Enabled = false;
            }
            else
            {
                buttonItemNext.Enabled = true;
                buttonItemLast.Enabled = true;
            }

            if (comboBoxItemPages.Items.Count == 0)
            {
                int _StartRowNumber;
                int _EndRowNumber;

                for (int i = 1; i <= TotalPages; i++)
                {
                    _StartRowNumber = ((i - 1) * PageSize) + 1;
                    _EndRowNumber = i * PageSize;
                    if (_EndRowNumber > TotalItems)
                        _EndRowNumber = TotalItems;

                    comboBoxItemPages.Items.Add(string.Format(" Row {0} - {1}", _StartRowNumber.ToString(), _EndRowNumber.ToString()));
                }

            }
            m_SuspendIndexChanged = true;
            comboBoxItemPages.SelectedIndex = PageNumber - 1;
            m_SuspendIndexChanged = false;
            comboBoxItemPages.Enabled = true;
        }

        private void buttonItemFirst_Click(object sender, EventArgs e)
        {
            PageNumber = 1;
            StartAsynchLoad();
        }

        private void buttonItemPrevious_Click(object sender, EventArgs e)
        {

            PageNumber--;
            StartAsynchLoad();
        }

        private void buttonItemNext_Click(object sender, EventArgs e)
        {

            PageNumber++;
            StartAsynchLoad();
        }

        private void buttonItemLast_Click(object sender, EventArgs e)
        {
            PageNumber = TotalPages;
            StartAsynchLoad();
        }

        private void comboBoxItemPages_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (m_SuspendIndexChanged)
                return;

            PageNumber = comboBoxItemPages.SelectedIndex + 1;
            StartAsynchLoad();
        }

        #endregion

        #region Search

        [DefaultValue(Common.Enumerations.GridSearchByTpes.None), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Common.Enumerations.GridSearchByTpes CurrentSearchType { get; set; }

        [DefaultValue(null), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string CurrentSearchText { get; set; }

        protected void ShowSearch(string text)
        {
            buttonItemSearch.Text = text;
            buttonItemSearch.ButtonStyle = DevComponents.DotNetBar.eButtonStyle.ImageAndText;
            controlContainerItemSearchTextBox.Visible = true;
            buttonItemClearText.Visible = true;
            buttonItemGo.Visible = true;
            bar1.Refresh();
        }

        protected void ClearSearch()
        {
            buttonItemSearch.Text = string.Empty;
            buttonItemSearch.ButtonStyle = DevComponents.DotNetBar.eButtonStyle.Default;
            controlContainerItemSearchTextBox.Visible = false;
            textBoxItemSearch.Text = string.Empty;
            buttonItemClearText.Visible = false;
            buttonItemGo.Visible = false;
        }

        private void buttonItemSearch_Click(object sender, EventArgs e)
        {
            //
        }

        private void buttonItemClearText_Click(object sender, EventArgs e)
        {
            ClearSearch();
        }

        #endregion

        #region Context Menu/Main Bar methods that should be ovverriden in parent
        
        public virtual void DoSearch(Enumerations.GridSearchByTpes searchBy, string searchBytext)
        {
            //do nothing - all work should be implemented in parent
        }

        public virtual void DoExportToExcel()
        {
            //can be overridden if needed
            saveFileDialog1.FileName = string.Format("{0} Export {1}.xls", panelExTitle.Text, DateTime.Today.ToString("MM_dd_yyyy"));
            if (saveFileDialog1.ShowDialog() != DialogResult.OK)
                return;

            StartProgressIndicator();

            if (!backgroundWorkerExcelExport.IsBusy)
                backgroundWorkerExcelExport.RunWorkerAsync();
        }

        public virtual void DoEdit()
        {
            //do nothing - all work should be implemented in parent
        }

        public virtual void DoOpen()
        {
            //do nothing - all work should be implemented in parent
        }

        public virtual void DoMapForGrid()
        {
            //do nothing - all work should be implemented in parent
        }

        public virtual void DoMapForRecord()
        {
            //do nothing - all work should be implemented in parent
        }

        public virtual void DoRefresh()
        {
            StartAsynchLoad();
        }

        public virtual bool ContextShowAllowed()
        {
            //do nothing - all work should be implemented in parent
            return false;
        }

        #endregion

        protected void ShowKmlInMap()
        {
            Program.FormMain.MapControl.LoadKmlFromString(GridDataType, Kml);
        }

        private void buttonItemGo_Click(object sender, EventArgs e)
        {
            //DoSearch(
        }

        private void buttonItemOpen_Click(object sender, EventArgs e)
        {
            DoOpen();
        }

        private void buttonItemEdit_Click(object sender, EventArgs e)
        {
            DoEdit();
        }

        private void buttonItemViewOnMap_Click(object sender, EventArgs e)
        {
            DoMapForRecord();
        }

        private void buttonItemDirections_Click(object sender, EventArgs e)
        {
            string _baseURL;
            _baseURL = Program.GetSettingValue(Constants.Settings.DirectionsUrl);

            string _FromAddress;
            _FromAddress = (sender as DevComponents.DotNetBar.BaseItem).Tag.ToString();

            string _ToAddress;
            _ToAddress = string.Format("{0},{1}", SelectedRowLatitude.ToString().Replace(",", "."), SelectedRowLongitude.ToString().Replace(",", "."));

            string _DirectionUrl;
            _DirectionUrl = string.Format(_baseURL, _FromAddress, _ToAddress, DataKeyId, GridDataType);
            
            Program.FormMain.ShowDirections("Directions", _DirectionUrl);
        }

        private void contextMenuBarGrid_PopupOpen(object sender, DevComponents.DotNetBar.PopupOpenEventArgs e)
        {
            if (!ContextShowAllowed())
            {
                e.Cancel = true;
                return;
            }

            //only enable directions if we have longitutude and latitude
            if (!SelectedRowLatitude.HasValue || !SelectedRowLongitude.HasValue)
                buttonItemDirections.Enabled = false;
            else
                buttonItemDirections.Enabled = true;

            if (m_EditContextAllowed)
            {
                buttonItemEdit.Visible = true;
                buttonItemOpen.Visible = false;
            }
            else
            {
                buttonItemEdit.Visible = false;
                buttonItemOpen.Visible = GridDataType != Enumerations.DataTypes.AssetsDistribution && GridDataType != Enumerations.DataTypes.AssetsMeters && GridDataType != Enumerations.DataTypes.AssetsTransformers;
            }

            return;


            //needs to be defined on the grids

            ////TODO: delete this
            //buttonItemEdit.Visible = false;
            //buttonItemOpen.Visible = true;
            //return;
            //// ********************

            //switch (Program.LoginResult.LoginUserType)
            //{
            //    case PolePosition.v3.EntityLibrary.LoginEntity.LoginUserTypes.Unknown:
            //        buttonItemEdit.Visible = false;
            //        buttonItemOpen.Visible = false;
            //        break;
            //    case PolePosition.v3.EntityLibrary.LoginEntity.LoginUserTypes.Vendor:
            //        buttonItemEdit.Visible = true;
            //        buttonItemOpen.Visible = false;
            //        break;
            //    case PolePosition.v3.EntityLibrary.LoginEntity.LoginUserTypes.Utility:
            //        buttonItemEdit.Visible = false;
            //        buttonItemOpen.Visible = true;
            //        break;
            //    case PolePosition.v3.EntityLibrary.LoginEntity.LoginUserTypes.PPI:
            //        buttonItemEdit.Visible = true;
            //        buttonItemOpen.Visible = false;
            //        break;
            //    default:
            //        break;
            //} 
        }

        private void buttonItemMap_Click(object sender, EventArgs e)
        {
            DoMapForGrid();
        }

        private void buttonItemRefresh_Click(object sender, EventArgs e)
        {
            DoRefresh();
        }

        private void buttonItemExcel_Click(object sender, EventArgs e)
        {
            DoExportToExcel();
        }


        protected void ShowExcelExportResults(DataTable table)
        {
            CarlosAg.ExcelXmlWriter.Workbook _Workbook;
            _Workbook = new CarlosAg.ExcelXmlWriter.Workbook();

            CarlosAg.ExcelXmlWriter.Worksheet _WorkSheet;
            _WorkSheet = _Workbook.Worksheets.Add(panelExTitle.Text);

            // Add some styles to the Workbook
            CarlosAg.ExcelXmlWriter.WorksheetStyle style = _Workbook.Styles.Add("HeaderStyle");
            style.Font.FontName = "Tahoma";
            style.Font.Size = 10;
            style.Alignment.Horizontal = CarlosAg.ExcelXmlWriter.StyleHorizontalAlignment.Center;
            style.Font.Color = "White";
            style.Interior.Color = "DarkBlue";
            style.Interior.Pattern = CarlosAg.ExcelXmlWriter.StyleInteriorPattern.Solid;

            // Create the Default Style to use for everyone
            style = _Workbook.Styles.Add("Default");
            style.Font.FontName = "Tahoma";
            style.Font.Size = 10;
            style.Alignment.Horizontal = CarlosAg.ExcelXmlWriter.StyleHorizontalAlignment.Center;

            _WorkSheet.Table.DefaultColumnWidth = 150;

            CarlosAg.ExcelXmlWriter.WorksheetRow _WorksheetRow;
            _WorksheetRow = _WorkSheet.Table.Rows.Add();

            foreach (DataColumn _Column in table.Columns)
            {
                _WorksheetRow.Cells.Add(_Column.ColumnName, CarlosAg.ExcelXmlWriter.DataType.String, "HeaderStyle");
            }

            string _Value;
            foreach (DataRow _Row in table.Rows)
            {
                _WorksheetRow = _WorkSheet.Table.Rows.Add();
                foreach (DataColumn _Column in table.Columns)
                {

                    if (_Row[_Column] == DBNull.Value)
                        _Value = null;
                    else
                        _Value = _Row[_Column].ToString();

                    _WorksheetRow.Cells.Add(_Value, CarlosAg.ExcelXmlWriter.DataType.String, "Default");
                }
            }

            _Workbook.Save(saveFileDialog1.FileName);

            DialogResult _OpenResult;
            _OpenResult = DevComponents.DotNetBar.MessageBoxEx.Show("File saved. Would you like to open the file now?", "Open File", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (_OpenResult == DialogResult.Yes)
                System.Diagnostics.Process.Start(saveFileDialog1.FileName);
        }
    }
}
